{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "from tensorflow.python.framework import ops\n",
    "ops.reset_default_graph()\n",
    "sess = tf.Session()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_size = 25\n",
    "data_1d = np.random.normal(size=data_size)\n",
    "x_input_1d = tf.placeholder(dtype=tf.float32, shape=[data_size])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def conv_layer_1d(input_1d, my_filter):\n",
    "    input_2d = tf.expand_dims(input_1d, 0)\n",
    "    input_3d = tf.expand_dims(input_2d, 0)\n",
    "    input_4d = tf.expand_dims(input_3d, 3)\n",
    "    convolution_output = tf.nn.conv2d(input_4d, filter=my_filter, strides=[1,1,1,1], padding=\"VALID\")\n",
    "    conv_output_1d = tf.squeeze(convolution_output)\n",
    "    return(conv_output_1d)\n",
    "my_filter = tf.Variable(tf.random_normal(shape=[1,5,1,1]))\n",
    "my_convolution_output = conv_layer_1d(x_input_1d, my_filter)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def activation(input_1d):\n",
    "    return(tf.nn.relu(input_1d))\n",
    "my_activation_output = activation(my_convolution_output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def max_pool(input_1d, width):\n",
    "    input_2d = tf.expand_dims(input_1d, 0)\n",
    "    input_3d = tf.expand_dims(input_2d, 0)\n",
    "    input_4d = tf.expand_dims(input_3d, 3)\n",
    "    pool_output = tf.nn.max_pool(input_4d, ksize=[1, 1, width, 1],\n",
    "                                 strides=[1, 1, 1, 1],\n",
    "                                 padding='VALID')\n",
    "    pool_output_1d = tf.squeeze(pool_output)\n",
    "    return(pool_output_1d)\n",
    "my_maxpool_output = max_pool(my_activation_output, width=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fully_connected(input_layer, num_outputs):\n",
    "    weight_shape = tf.squeeze(tf.stack([tf.shape(input_layer),[num_outputs]]))\n",
    "    weight = tf.random_normal(weight_shape, stddev=0.1)\n",
    "    bias = tf.random_normal(shape=[num_outputs])\n",
    "    input_layer_2d = tf.expand_dims(input_layer, 0)\n",
    "    full_output = tf.add(tf.matmul(input_layer_2d, weight), bias)\n",
    "    full_output_1d = tf.squeeze(full_output)\n",
    "    return(full_output_1d)\n",
    "my_full_output = fully_connected(my_maxpool_output, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input = array of length 25\n",
      "Convolution w/filter, length = 5, stride size = 1, results in an array of length 21:\n",
      "[-3.646209    0.9045732   2.32889366 -0.11598274 -0.87132847  1.44859242\n",
      " -1.76004124 -2.50407505 -1.17141294 -0.69335902  1.11122119 -4.46349525\n",
      " -0.73472703 -0.06231488  3.86247611 -1.50562584 -0.87364674 -0.68837315\n",
      " -2.46940207  2.51993799 -1.62778318]\n",
      "\n",
      "Input = the above array of length 21\n",
      "ReLU element wise returns the array of length 21:\n",
      "[ 0.          0.9045732   2.32889366  0.          0.          1.44859242\n",
      "  0.          0.          0.          0.          1.11122119  0.          0.\n",
      "  0.          3.86247611  0.          0.          0.          0.\n",
      "  2.51993799  0.        ]\n",
      "\n",
      "Input = the above array of length 21\n",
      "MaxPool, window length = 5, stride size = 1, results in the array of length 17:\n",
      "[ 2.32889366  2.32889366  2.32889366  1.44859242  1.44859242  1.44859242\n",
      "  1.11122119  1.11122119  1.11122119  1.11122119  3.86247611  3.86247611\n",
      "  3.86247611  3.86247611  3.86247611  2.51993799  2.51993799]\n",
      "\n",
      "Input = the above array of length 17\n",
      "Fully connected layer on all four rows with five outputs:\n",
      "[-0.71787554 -1.2916398   1.79132366  1.65761411  1.3989687 ]\n"
     ]
    }
   ],
   "source": [
    "init = tf.global_variables_initializer()\n",
    "sess.run(init)\n",
    "feed_dict = {x_input_1d: data_1d}\n",
    "print('Input = array of length 25')\n",
    "print('Convolution w/filter, length = 5, stride size = 1, results in an array of length 21:')\n",
    "print(sess.run(my_convolution_output, feed_dict=feed_dict))\n",
    "print('\\nInput = the above array of length 21')\n",
    "print('ReLU element wise returns the array of length 21:')\n",
    "print(sess.run(my_activation_output, feed_dict=feed_dict))\n",
    "print('\\nInput = the above array of length 21')\n",
    "print('MaxPool, window length = 5, stride size = 1, results in the array of length 17:')\n",
    "print(sess.run(my_maxpool_output, feed_dict=feed_dict))\n",
    "print('\\nInput = the above array of length 17')\n",
    "print('Fully connected layer on all four rows with five outputs:')\n",
    "print(sess.run(my_full_output, feed_dict=feed_dict))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "ops.reset_default_graph()\n",
    "sess = tf.Session()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_size = [10,10]\n",
    "data_2d = np.random.normal(size=data_size)\n",
    "x_input_2d = tf.placeholder(dtype=tf.float32, shape=data_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def conv_layer_2d(input_2d, my_filter):\n",
    "    input_3d = tf.expand_dims(input_2d, 0)\n",
    "    input_4d = tf.expand_dims(input_3d, 3)\n",
    "    convolution_output = tf.nn.conv2d(input_4d, filter=my_filter, strides=[1,2,2,1], padding=\"VALID\")\n",
    "    conv_output_2d = tf.squeeze(convolution_output)\n",
    "    return(conv_output_2d)\n",
    "my_filter = tf.Variable(tf.random_normal(shape=[2,2,1,1]))\n",
    "my_convolution_output = conv_layer_2d(x_input_2d, my_filter)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def activation(input_2d):\n",
    "    return(tf.nn.relu(input_2d))\n",
    "my_activation_output = activation(my_convolution_output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def max_pool(input_2d, width, height):\n",
    "    input_3d = tf.expand_dims(input_2d, 0)\n",
    "    input_4d = tf.expand_dims(input_3d, 3)\n",
    "    pool_output = tf.nn.max_pool(input_4d, ksize=[1, height, width, 1],\n",
    "                                 strides=[1, 1, 1, 1],\n",
    "                                 padding='VALID')\n",
    "    pool_output_2d = tf.squeeze(pool_output)\n",
    "    return(pool_output_2d)\n",
    "my_maxpool_output = max_pool(my_activation_output, width=2, height=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fully_connected(input_layer, num_outputs):\n",
    "    flat_input = tf.reshape(input_layer, [-1])\n",
    "    weight_shape = tf.squeeze(tf.stack([tf.shape(flat_input),[num_outputs]]))\n",
    "    weight = tf.random_normal(weight_shape, stddev=0.1)\n",
    "    bias = tf.random_normal(shape=[num_outputs])\n",
    "    input_2d = tf.expand_dims(flat_input, 0)\n",
    "    full_output = tf.add(tf.matmul(input_2d, weight), bias)\n",
    "    full_output_2d = tf.squeeze(full_output)\n",
    "    return(full_output_2d)\n",
    "my_full_output = fully_connected(my_maxpool_output, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "init = tf.global_variables_initializer()\n",
    "sess.run(init)\n",
    "feed_dict = {x_input_2d: data_2d}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input = [10 X 10] array\n",
      "2x2 Convolution, stride size = [2x2], results in the [5x5] array:\n",
      "[[ 2.60103631 -1.53552842 -1.68671465  3.11533427 -3.52291489]\n",
      " [ 7.5114975  -2.48186564  0.32743108 -0.84987295 -0.38588881]\n",
      " [-0.23601067  1.22517467  0.79208016 -0.66182518 -0.22458503]\n",
      " [-1.00660574 -3.70954537 -0.0976584  -1.02609503 -2.26884246]\n",
      " [ 1.18578267 -0.60996336  1.42970955 -6.30630445  0.05838838]]\n",
      "\n",
      "Input = the above [5x5] array\n",
      "ReLU element wise returns the [5x5] array:\n",
      "[[ 2.60103631  0.          0.          3.11533427  0.        ]\n",
      " [ 7.5114975   0.          0.32743108  0.          0.        ]\n",
      " [ 0.          1.22517467  0.79208016  0.          0.        ]\n",
      " [ 0.          0.          0.          0.          0.        ]\n",
      " [ 1.18578267  0.          1.42970955  0.          0.05838838]]\n",
      "\n",
      "Input = the above [5x5] array\n",
      "MaxPool, stride size = [1x1], results in the [4x4] array:\n",
      "[[ 7.5114975   0.32743108  3.11533427  3.11533427]\n",
      " [ 7.5114975   1.22517467  0.79208016  0.        ]\n",
      " [ 1.22517467  1.22517467  0.79208016  0.        ]\n",
      " [ 1.18578267  1.42970955  1.42970955  0.05838838]]\n",
      "\n",
      "Input = the above [4x4] array\n",
      "Fully connected layer on all four rows with five outputs:\n",
      "[ 1.15000248  0.30244893 -1.02720189 -1.14666045  2.47171283]\n"
     ]
    }
   ],
   "source": [
    "print('Input = [10 X 10] array')\n",
    "print('2x2 Convolution, stride size = [2x2], results in the [5x5] array:')\n",
    "print(sess.run(my_convolution_output, feed_dict=feed_dict))\n",
    "print('\\nInput = the above [5x5] array')\n",
    "print('ReLU element wise returns the [5x5] array:')\n",
    "print(sess.run(my_activation_output, feed_dict=feed_dict))\n",
    "print('\\nInput = the above [5x5] array')\n",
    "print('MaxPool, stride size = [1x1], results in the [4x4] array:')\n",
    "print(sess.run(my_maxpool_output, feed_dict=feed_dict))\n",
    "print('\\nInput = the above [4x4] array')\n",
    "print('Fully connected layer on all four rows with five outputs:')\n",
    "print(sess.run(my_full_output, feed_dict=feed_dict))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
